package com.zhike.service.system.impl;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageHelper;
import com.zhike.common.constant.SysConfigConstants;
import com.zhike.common.exception.ZkimException;
import com.zhike.common.model.SystemConfig;
import com.zhike.common.utils.RedisFactory;
import com.zhike.common.utils.RedisService;
import com.zhike.mapper.system.SystemConfigMapper;
import com.zhike.service.system.ISystemConfigService;
import org.springframework.beans.factory.annotation.Autowired;

import cn.hutool.core.util.StrUtil;
import redis.clients.jedis.Jedis;

@Service
public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigMapper, SystemConfig>
        implements ISystemConfigService {

    @Resource
    private SystemConfigMapper systemConfigMapper;

    @Autowired
    private RedisService redisService;

    /**
     * 在系统启动初始化时
     * 根据配置文件加载config_list缓存
     */
    @EventListener(ApplicationReadyEvent.class)
    public void loadingConfigCache() {
        // if (!zkimConfig.getAsyncConfig()) {
        // return;
        // }
        // 注释下面代码，是为了每次启动更新redis, 前提是asyncConfig是true
        // if (redisUtil.exists(SysConfigConstants.CONFIG_LIST)) {
        // Long hashSize = redisUtil.getHashSize(SysConfigConstants.CONFIG_LIST);
        // if (hashSize > 0) {
        // return;
        // }
        // }

        LambdaQueryWrapper<SystemConfig> lqw = Wrappers.lambdaQuery();
        lqw.select(SystemConfig::getType, SystemConfig::getName, SystemConfig::getValue);
        List<SystemConfig> systemConfigList = systemConfigMapper.selectList(lqw);
        systemConfigList
                .forEach(config -> {
                    if (StringUtils.isNotBlank(config.getValue())) {
                        redisService.hSet(SysConfigConstants.CONFIG_LIST,
                                config.getType() + "_" + config.getName(), config.getValue());
                    }
                });

    }

    @Override
    public String getValueByKey(String type, String name) {
        return get(type, name);
    }

    @Override
    public String getValueByKey(String type, String name, String defaultValue) {
        return StringUtils.isBlank(get(type, name)) ? defaultValue : get(type, name);
    }

    @Override
    public Boolean updateOrSaveValueByName(String type, String name, String value) {
        LambdaQueryWrapper<SystemConfig> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(SystemConfig::getType, type);
        lambdaQueryWrapper.eq(SystemConfig::getName, name);
        List<SystemConfig> systemConfigs = systemConfigMapper.selectList(lambdaQueryWrapper);
        if (systemConfigs.size() >= 2) {
            throw new ZkimException("配置名称存在多个请检查配置 zhike_system_config 重复数据：" + name + "条数：" + systemConfigs.size());
        } else if (systemConfigs.size() == 1) {
            SystemConfig systemConfig = systemConfigs.get(0);
            systemConfig.setValue(value);
            boolean update = updateById(systemConfig);
            if (update) {
                async(systemConfig);
            }
            return update;
        } else {
            SystemConfig systemConfig = new SystemConfig().setType(type).setName(name).setValue(value);
            boolean save = save(systemConfig);
            if (save) {
                async(systemConfig);
            }
            return save;
        }
    }

    @Override
    public String getValueByKeyException(String type, String name) {
        String value = get(type, name);
        if (StrUtil.isBlank(value)) {
            throw new ZkimException("没有找到或配置：" + name + "数据");
        }
        return value;
    }

    @Override
    public Boolean checkName(String type, String name) {
        String value = get(type, name);
        return StrUtil.isBlank(value);
    }

    @Override
    public List<SystemConfig> getListByKey(String type, String key) {
        LambdaQueryWrapper<SystemConfig> lqw = Wrappers.lambdaQuery();
        lqw.eq(SystemConfig::getType, type);
        lqw.eq(SystemConfig::getName, key);
        return systemConfigMapper.selectList(lqw);
    }

    /**
     * 把数据同步到redis
     *
     * @param name String
     * @return String
     */
    private String get(String type, String name) {
        // if (!zkimConfig.getAsyncConfig()) {
        // SystemConfig systemConfig = getByName(name);
        // if (ObjectUtil.isNull(systemConfig) ||
        // StrUtil.isBlank(systemConfig.getValue())) {
        // return "";
        // }
        // return systemConfig.getValue();
        // }

        Long size = redisService.hLen(SysConfigConstants.CONFIG_LIST);
        if (size <= 0) {
            SystemConfig systemConfig = getByName(type, name);
            if (ObjectUtil.isNull(systemConfig) || StrUtil.isBlank(systemConfig.getValue())) {
                asyncBlank(type, name);
                return "";
            }
            async(systemConfig);
            return systemConfig.getValue();
        }
        Object data = redisService.hGet(SysConfigConstants.CONFIG_LIST, type + "_" + name);
        if (ObjectUtil.isNull(data)) {
            asyncBlank(type, name);
            return "";
        }
        return data.toString();
    }

    private SystemConfig getByName(String type, String name) {
        PageHelper.clearPage();
        LambdaQueryWrapper<SystemConfig> lqw = Wrappers.lambdaQuery();
        lqw.select(SystemConfig::getId, SystemConfig::getType, SystemConfig::getName, SystemConfig::getValue);
        lqw.eq(SystemConfig::getType, type);
        lqw.eq(SystemConfig::getName, name);
        lqw.last(" limit 1");
        return getOne(lqw);
    }

    private void asyncBlank(String type, String key) {
        redisService.hSet(SysConfigConstants.CONFIG_LIST, type + "_" + key, "");
    }

    private void async(SystemConfig systemConfig) {
        redisService.hSet(SysConfigConstants.CONFIG_LIST, systemConfig.getType() + "_" + systemConfig.getName(),
                systemConfig.getValue());
    }

    @Override
    public Integer getValueByKeyAsInt(String type, String key) {
        return Integer.parseInt(getValueByKey(type, key));
    }

    @Override
    public Integer getValueByKeyAsInt(String type, String key, String defaultValue) {
        return Integer.parseInt(getValueByKey(type, key, defaultValue));
    }

    @Override
    public boolean syncCache(String type, String key, String val) {
        SystemConfig config = new SystemConfig();
        LambdaUpdateWrapper<SystemConfig> luw = new LambdaUpdateWrapper<>();
        luw.set(SystemConfig::getValue, val);
        luw.eq(SystemConfig::getType, type)
                .eq(SystemConfig::getName, key);
        if (systemConfigMapper.update(config, luw) > 0) {
            Jedis jedis = null;
            try {
                jedis = RedisFactory.getJedis();
                jedis.hset(SysConfigConstants.CONFIG_LIST,
                        config.getType() + "_" + config.getName(), config.getValue());
                return Boolean.TRUE;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                jedis.close();
            }
        }
        return Boolean.FALSE;
    }

    @Override
    public void syncCacheAll() {
        loadingConfigCache();
    }

}
